#!/usr/bin/env node

var fs = require('fs');
var path = require('path');

var FFI = require('node-ffi');
var libc = new FFI.Library(null, {'system': ['int32', ['string']]});
var exec = libc.system;

var jsRequire = require.extensions['.js'];
require.extensions['.js'] = function(module, filename) {
  var baseFile = path.relative(path.join(__dirname, '..'), filename);
  if (baseFile.match(/^lib\//)) {
    filename = filename.replace(/\/lib\//, '/lib-cov/');
  }
  jsRequire(module, filename);
}

function printStats(file, covered, total) {
  var maxFileLength = 26;
  var pad = maxFileLength - file.length;
  for (var i = 0; i < pad; i++) file += ' ';
  console.log(file + '   ' +
    (parseFloat(covered) / parseFloat(total) * 100).toFixed(2) + '%' +
    ((covered != total) ? '  ' : ' ') +
    '(' + covered + '/' + total + ')');
}

function cleanup() {
  exec('rm -rf lib-cov');
}

process.on('uncaughtException', function(err) {
  cleanup();
  throw err;
});

process.on('exit', function() {
  var out = 'NO COVERAGE';
  if (typeof(_$jscoverage) !== 'undefined') {
    var stats = {}
    var entireCovered = 0;
    var entireTotal = 0;
    out = '';
    var cov = _$jscoverage;
    for (var file in cov) {
      stats[file] = {covered: 0, total: 0};
      var id = file.replace(/[\.\/]/, '_');
      var total = cov[file].length;
      var uncovered = 0;
      for (var idx in cov[file]) {
        if (cov[file][idx] === 0) uncovered++;
      }
      var covered = total - uncovered;
      stats[file].covered = covered;
      stats[file].total = total;
      entireCovered += covered;
      entireTotal += total;

      out += '<h2>' + file + ' <small>(' + covered + '/' + total + ', ' +
        (parseFloat(covered) / parseFloat(total) * 100).toFixed(2) +
        '% covered) [<a href="#code_'+id+'" id="show_' + id + '">+</a>]</small></h2>\n';
      var lineAccess = [];

      out += "<table border='0' cellspacing='0' width='95%' style='display:none' id='code_"+id+"'>";
      for (var lineNo in cov[file].source) {
        lineNo = parseInt(lineNo);
        out += "<tr class='count_"+cov[file][lineNo+1]+"'>";
        out += "<td align='right'>"+(lineNo+1)+"</td><td width='60'></td><td>";
        out += "<pre>" + cov[file].source[lineNo] + "</pre>";
        out += "</td></tr>\n";
      }
      out += "\n</table>\n";
    }
    out += '<script>\n' +
      'function scriptToggleHandler(id) {\n' +
      ' var link = document.getElementById("show_"+id);\n' +
      ' var code = document.getElementById("code_"+id);\n' +
      ' link.addEventListener("click", function() {\n' +
      '   if (link.innerText == "+") {\n' +
      '     link.innerText = "-";\n' +
      '     code.style.display = "block";\n' +
      '   } else if (link.innerText == "-") {\n' +
      '     link.innerText = "+";\n' +
      '     code.style.display = "none";\n' +
      '   }\n' +
      '   return false;\n' +
      ' }, false);\n' +
      '}\n';
    for (var file in cov) {
      var id = file.replace(/[\.\/]/, '_');
      out += 'scriptToggleHandler("'+id+'");\n';
    }
    out += '\n</script>';
  }
  var head = "<style>tr { background: #ddffdd; }\ntr.count_undefined " +
    "{ background: transparent; }\ntr.count_0 { background: #ffdddd; }\nh1 small { font-size: 0.6em; }</style>";
  var body = out;
  body = "<p>Total coverage: " + (parseFloat(entireCovered) / parseFloat(entireTotal) * 100).toFixed(2) + "%</p>\n" + body;
  var page = "<html>\n<head>\n"+head+"\n</head>\n<body>\n"+body+"\n</body>\n</html>\n";
  fs.writeFileSync('coverage.html', page);

  console.log('Test coverage:\n');
  var files = [];
  for (var file in stats) {
    files.push([file, stats[file]]);
  }
  files.sort(function(a, b) {
    var aVal = parseFloat(a[1].covered) / parseFloat(a[1].total);
    var bVal = parseFloat(b[1].covered) / parseFloat(b[1].total);
    return (aVal > bVal ? -1 : 1);
  });
  for (var item in files) {
    var file = files[item][0];
    var stats = files[item][1];
    printStats(file, stats.covered, stats.total)
  }

  console.log('');
  printStats('Total', entireCovered, entireTotal);

  cleanup();
});

exec('./node_modules/visionmedia-jscoverage/jscoverage lib lib-cov')
require(path.join(__dirname, '../node_modules/jasmine-node/lib/jasmine-node/cli.js'));
